package xyz.zcq.zcqrpc.easy.server;

import io.vertx.core.Handler;
import io.vertx.core.buffer.Buffer;
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.http.HttpServerResponse;
import xyz.zcq.zcqrpc.easy.model.RpcRequest;
import xyz.zcq.zcqrpc.easy.model.RpcResponse;
import xyz.zcq.zcqrpc.easy.registry.LocalImplRegistry;
import xyz.zcq.zcqrpc.easy.serializer.JdkSerializer;
import xyz.zcq.zcqrpc.easy.serializer.Serializer;

import java.io.IOException;
import java.lang.reflect.Method;

/**
 * HTTP请求处理
 */
public class HttpServerHandler implements Handler<HttpServerRequest> {

    @Override
    public void handle(HttpServerRequest request) {
        // 记录日志
        System.out.println("Received request: " + request.method() + " " + request.uri());
        // 获取序列化器
        Serializer serializer = new JdkSerializer();
        // 处理请求
        request.bodyHandler(buffer -> {
            // 获取请求体，转化为RpcRequest
            byte[] reqBody = buffer.getBytes();
            RpcRequest rpcRequest = null;
            Exception ex = null;
            try {
                rpcRequest = serializer.deserialization(reqBody, RpcRequest.class);
            } catch (IOException e) {
                ex = e;
            }
            // 构造RpcRequest，发送响应
            doResponse(request, serializer, buildRpcResponse(rpcRequest, ex));
        });
    }

    private static RpcResponse buildRpcResponse(RpcRequest rpcRequest, Exception ex) {
        RpcResponse rpcResponse = new RpcResponse();
        if (rpcRequest == null) {
            rpcResponse.setMessage("request deserialization exception");
            rpcResponse.setException(ex);
            return rpcResponse;
        }
        Class<?> serviceImplClazz = LocalImplRegistry.get(rpcRequest.getServiceName());
        try {
            Method method = serviceImplClazz.getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
            Object result = method.invoke(serviceImplClazz.newInstance(), rpcRequest.getParameters());
            rpcResponse.setData(result);
            rpcResponse.setDataType(method.getReturnType());
            rpcResponse.setMessage("ok");
        } catch (Exception e) {
            e.printStackTrace();
            rpcResponse.setMessage(e.getMessage());
            rpcResponse.setException(e);
        }
        return rpcResponse;
    }

    private static void doResponse(HttpServerRequest request, Serializer serializer, RpcResponse rpcResponse) {
        HttpServerResponse response = request.response().putHeader("contentType", "application/json");
        try {
            byte[] resBody = serializer.serialize(rpcResponse);
            response.end(Buffer.buffer(resBody));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

}
